package com.jackfruit.aspectjrxpermissions.rxpermissions2;

import android.annotation.TargetApi;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;

import java.util.HashMap;
import java.util.Map;

import io.reactivex.subjects.PublishSubject;

public class RxPermissionsFragment extends Fragment {

  private static final int PERMISSIONS_REQUEST_CODE = 42;
  private static final String TAG = "RxPermissionsFragment";
  // Contains all the current permission requests.
  // Once granted or denied, they are removed from it.
  private Map< String, PublishSubject<Permission>> mSubjects = new HashMap<>();
  private boolean mLogging;

  public RxPermissionsFragment() {}

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);
  }

  @TargetApi(Build.VERSION_CODES.M)
  void requestPermissions(@NonNull String[] permissions) {
    requestPermissions(permissions, PERMISSIONS_REQUEST_CODE);
  }

  @Override
  @TargetApi(Build.VERSION_CODES.M)
  public void onRequestPermissionsResult(
      int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (requestCode != PERMISSIONS_REQUEST_CODE) {
      return;
    }

    boolean[] shouldShowRequestPermissionRationale = new boolean[permissions.length];

    for (int i = 0; i < permissions.length; i++) {
      shouldShowRequestPermissionRationale[i] =
          shouldShowRequestPermissionRationale(permissions[i]);
    }

    onRequestPermissionsResult(permissions, grantResults, shouldShowRequestPermissionRationale);
  }

  void onRequestPermissionsResult(
      String permissions[], int[] grantResults, boolean[] shouldShowRequestPermissionRationale) {
    for (int i = 0, size = permissions.length; i < size; i++) {
      LogUtils("onRequestPermissionsResult  " + permissions[i]);
      // Find the corresponding subject
      PublishSubject<Permission> subject = mSubjects.get(permissions[i]);
      if (subject == null) {
        // No subject found
        Log.e(
            TAG,
            "RxPermissions.onRequestPermissionsResult invoked but didn't find the corresponding permission request.");
        return;
      }
      mSubjects.remove(permissions[i]);
      boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
      subject.onNext(
          new Permission(permissions[i], granted, shouldShowRequestPermissionRationale[i]));
      subject.onComplete();
    }
  }

  @TargetApi(Build.VERSION_CODES.M)
  boolean isGranted(String permission) {
    final FragmentActivity fragmentActivity = getActivity();
    if (fragmentActivity == null) {
      throw new IllegalStateException("This fragment must be attached to an activity.");
    }
    return fragmentActivity.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
  }

  @TargetApi(Build.VERSION_CODES.M)
  boolean isRevoked(String permission) {
    final FragmentActivity fragmentActivity = getActivity();
    if (fragmentActivity == null) {
      throw new IllegalStateException("This fragment must be attached to an activity.");
    }
    return fragmentActivity
        .getPackageManager()
        .isPermissionRevokedByPolicy(permission, getActivity().getPackageName());
  }

  public void setLogging(boolean logging) {
    mLogging = logging;
  }

  public PublishSubject<Permission> getSubjectByPermission(@NonNull String permission) {
    return mSubjects.get(permission);
  }

  public boolean containsByPermission(@NonNull String permission) {
    return mSubjects.containsKey(permission);
  }

  public void setSubjectForPermission(
      @NonNull String permission, @NonNull PublishSubject<Permission> subject) {
    mSubjects.put(permission, subject);
  }

  void LogUtils(String message) {
    if (mLogging) {
      Log.d(TAG, message);
    }
  }
}
